# import numpy as np
# from scipy.optimize import minimize_scalar
# import matplotlib.pyplot as plt
# from mpl_toolkits.mplot3d import Axes3D
# plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置中文字体
# plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题
# # ============ 场景常量 ============
# g = 9.81  # m/s^2
# R = 10.0  # 有效遮蔽半径（云团中心 10 m）
# v_sink = 3  # 云团中心下沉速度 m/s
# valid_win = 20  # 起爆后有效 20 s
# T = np.array([0, 200, 0])  # 真目标中心
# Of = np.array([0, 0, 0])  # 假目标（原点）
#
# # 导弹 M1
# M0 = np.array([20000, 0, 2000])
# uM = (Of - M0) / np.linalg.norm(Of - M0)  # 朝向假目标
# vM = 300 * uM  # 速度 300 m/s
# L = np.linalg.norm(Of - M0)
# t_hit = L / 300  # 抵达假目标时间 ~ 67 s
#
# # 三架 UAV 初始位置（等高度直线飞行，z 保持不变）
# FY = np.array([
#     [17800, 0, 1800],  # FY1
#     [12000, 1400, 1400],  # FY2
#     [6000, -3000, 700]  # FY3
# ])
# v_min = 70
# v_max = 140
#
# # ============ 搜索网格（可调） ============
# angles = np.deg2rad(np.arange(-180, 180, 22.5))  # 航向角（相对 +x 逆时针）
# speeds = np.arange(70, 150, 10)  # 速度
# t_grid = np.arange(2, t_hit - 2, 2)  # 候选起爆时刻（全局时间）
# tau_set = np.array([2.4, 3.0, 3.6, 4.2])  # 候选引信延时
# dt_eval = 0.02  # 评估时间步长
#
# # ============ 预计算导弹/视线量 ============
# ts = np.arange(0, t_hit - 1e-6, dt_eval)  # 避免 t_hit 处除零
# N = len(ts)
# Mx = M0[0] + vM[0] * ts
# My = M0[1] + vM[1] * ts
# Mz = M0[2] + vM[2] * ts
# Ux = T[0] - Mx
# Uy = T[1] - My
# Uz = T[2] - Mz
# UU = Ux ** 2 + Uy ** 2 + Uz ** 2
#
# # ============ 贪心三弹（跨三架 UAV） ============
# dmin_all = np.full(N, np.inf)  # 当前联合最小距离
# uav_used = np.zeros(3, dtype=bool)  # 每架 UAV 仅用一次
#
#
# # 定义计划结构
# class Plan:
#     def __init__(self):
#         self.uav = 0
#         self.theta = 0
#         self.v = 0
#         self.t_rel = 0
#         self.tau = 0
#         self.t_det = 0
#         self.D = np.zeros(3)
#         self.C0 = np.zeros(3)
#
#
# plan = []
#
# for shot in range(3):
#     best_gain = -np.inf
#     best_info = Plan()
#     best_dmin_new = None
#
#     for iu in range(3):
#         if uav_used[iu]:
#             continue
#
#         F0 = FY[iu, :]
#         z0 = F0[2]
#
#         for ia in range(len(angles)):
#             theta = angles[ia]
#             uxF = np.cos(theta)
#             uyF = np.sin(theta)
#
#             for iv in range(len(speeds)):
#                 vF = speeds[iv]
#
#                 for id in range(len(t_grid)):
#                     t_det = t_grid[id]
#
#                     for it in range(len(tau_set)):
#                         tau = tau_set[it]
#                         t_rel = t_det - tau
#
#                         if t_rel < 0:
#                             continue
#
#                         # 起爆点 = UAV 位置(t_det) 与自由落体
#                         x_det = F0[0] + vF * uxF * t_det
#                         y_det = F0[1] + vF * uyF * t_det
#                         z_det = z0 - 0.5 * g * tau ** 2
#
#                         # 云团中心（仅在有效窗内）
#                         valid = (ts >= t_det) & (ts <= t_det + valid_win)
#                         Cz = z_det - v_sink * (ts - t_det)
#
#                         # 该弹对"导弹->真目标"线段的最小距离 d_k(t)
#                         Wx = x_det - Mx
#                         Wy = y_det - My
#                         Wz = Cz - Mz
#
#                         WU = Wx * Ux + Wy * Uy + Wz * Uz
#                         lam = WU / UU
#                         lam = np.clip(lam, 0, 1)
#
#                         Px = Mx + lam * Ux
#                         Py = My + lam * Uy
#                         Pz = Mz + lam * Uz
#
#                         dx = x_det - Px
#                         dy = y_det - Py
#                         dz = Cz - Pz
#                         d_k = np.sqrt(dx ** 2 + dy ** 2 + dz ** 2)
#                         d_k[~valid] = np.inf
#
#                         # 与现有联合取最小
#                         dmin_new = np.minimum(dmin_all, d_k)
#                         gain = np.sum(dmin_new <= R) * dt_eval
#
#                         if gain > best_gain:
#                             best_gain = gain
#                             best_dmin_new = dmin_new.copy()
#
#                             best_info = Plan()
#                             best_info.uav = iu
#                             best_info.theta = theta
#                             best_info.v = vF
#                             best_info.t_rel = t_rel
#                             best_info.tau = tau
#                             best_info.t_det = t_det
#                             best_info.D = np.array([
#                                 F0[0] + vF * uxF * t_rel,
#                                 F0[1] + vF * uyF * t_rel,
#                                 z0
#                             ])
#                             best_info.C0 = np.array([x_det, y_det, z_det])
#
#     # 接受该次最优
#     if best_gain == -np.inf:
#         print(f'Warning: No feasible solution found for shot {shot + 1}.')
#         break
#
#     dmin_all = best_dmin_new
#     uav_used[best_info.uav] = True
#     plan.append(best_info)
#
# total_cov = np.sum(dmin_all <= R) * dt_eval
#
# # ============ 输出结果 ============
# print('========= Problem 4: Optimal Obscuration Strategy (FY1, FY2, FY3 → M1) =========')
# for k, p in enumerate(plan):
#     name = f'FY{p.uav + 1}'
#     print(f'—— {name} ——')
#     print(f'Heading angle θ = {np.rad2deg(p.theta):.2f}° (relative to +x, counterclockwise)')
#     print(f'Flight speed v = {p.v:.2f} m/s')
#     print(f'Release time t_rel = {p.t_rel:.3f} s')
#     print(f'Fuse delay τ = {p.tau:.3f} s')
#     print(f'Detonation time t_det = {p.t_det:.3f} s')
#     print(f' Release point D = ({p.D[0]:.3f}, {p.D[1]:.3f}, {p.D[2]:.3f}) m')
#     print(f' Detonation point C0 = ({p.C0[0]:.3f}, {p.C0[1]:.3f}, {p.C0[2]:.3f}) m\n')
#
# print(f'Three-shot combined obscuration duration = {total_cov:.6f} s')
# if total_cov > 60 + 1e-6:
#     print('Warning: Theoretical maximum is 60 s (20 s per shot), current exceeds. Check grid/step settings.')
#
# # ============ 可视化 ============
# fig = plt.figure(figsize=(15, 10))
#
# # 1. 3D轨迹图
# ax1 = fig.add_subplot(2, 2, 1, projection='3d')
# colors = ['red', 'blue', 'green']
# markers = ['o', 's', '^']
#
# # 绘制导弹轨迹
# missile_t = np.linspace(0, t_hit, 100)
# missile_x = M0[0] + vM[0] * missile_t
# missile_y = M0[1] + vM[1] * missile_t
# missile_z = M0[2] + vM[2] * missile_t
# ax1.plot(missile_x, missile_y, missile_z, 'r-', label='Missile Trajectory')
#
# # 绘制视线
# line_x = np.linspace(M0[0], T[0], 100)
# line_y = np.linspace(M0[1], T[1], 100)
# line_z = np.linspace(M0[2], T[2], 100)
# ax1.plot(line_x, line_y, line_z, 'g--', label='Line of Sight')
#
# # 绘制UAV初始位置和轨迹
# for i in range(3):
#     ax1.scatter(FY[i, 0], FY[i, 1], FY[i, 2], color=colors[i], marker=markers[i], s=100, label=f'FY{i + 1} Start')
#
#     # 绘制UAV飞行方向（简化的直线）
#     if i < len(plan):
#         p = plan[i]
#         uav_dir_x = np.array([FY[i, 0], FY[i, 0] + 2000 * np.cos(p.theta)])
#         uav_dir_y = np.array([FY[i, 1], FY[i, 1] + 2000 * np.sin(p.theta)])
#         uav_dir_z = np.array([FY[i, 2], FY[i, 2]])
#         ax1.plot(uav_dir_x, uav_dir_y, uav_dir_z, color=colors[i], linestyle=':', alpha=0.7)
#
# # 绘制投放点和起爆点
# for i, p in enumerate(plan):
#     ax1.scatter(p.D[0], p.D[1], p.D[2], color=colors[p.uav], marker='*', s=150, label=f'FY{p.uav + 1} Release')
#     ax1.scatter(p.C0[0], p.C0[1], p.C0[2], color=colors[p.uav], marker='X', s=150, label=f'FY{p.uav + 1} Detonation')
#
# # 标记目标点
# ax1.scatter(T[0], T[1], T[2], color='black', marker='P', s=200, label='True Target')
# ax1.scatter(Of[0], Of[1], Of[2], color='orange', marker='D', s=200, label='False Target')
#
# ax1.set_xlabel('X (m)')
# ax1.set_ylabel('Y (m)')
# ax1.set_zlabel('Z (m)')
# ax1.set_title('3D Trajectory Overview')
# ax1.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
#
# # 2. 遮蔽效果时间序列
# ax2 = fig.add_subplot(2, 2, 2)
# ax2.plot(ts, dmin_all, 'b-', label='Min Distance to Line of Sight')
# ax2.axhline(y=R, color='r', linestyle='--', label='Effective Radius (10m)')
# ax2.fill_between(ts, 0, R, where=(dmin_all <= R), alpha=0.3, color='green', label='Obscuration Area')
#
# # 标记起爆时刻
# for i, p in enumerate(plan):
#     ax2.axvline(x=p.t_det, color=colors[p.uav], linestyle='--', alpha=0.7, label=f'FY{p.uav + 1} Detonation')
#
# ax2.set_xlabel('Time (s)')
# ax2.set_ylabel('Distance (m)')
# ax2.set_title('Obscuration Effect Over Time')
# ax2.legend()
# ax2.grid(True)
#
# # 3. XY平面投影
# ax3 = fig.add_subplot(2, 2, 3)
# ax3.plot(missile_x, missile_y, 'r-', label='Missile')
# ax3.plot(line_x, line_y, 'g--', label='Line of Sight')
#
# for i in range(3):
#     ax3.scatter(FY[i, 0], FY[i, 1], color=colors[i], marker=markers[i], s=100, label=f'FY{i + 1}')
#
# for i, p in enumerate(plan):
#     ax3.scatter(p.D[0], p.D[1], color=colors[p.uav], marker='*', s=150, label=f'FY{p.uav + 1} Release')
#     ax3.scatter(p.C0[0], p.C0[1], color=colors[p.uav], marker='X', s=150, label=f'FY{p.uav + 1} Detonation')
#
# ax3.scatter(T[0], T[1], color='black', marker='P', s=200, label='True Target')
# ax3.scatter(Of[0], Of[1], color='orange', marker='D', s=200, label='False Target')
#
# ax3.set_xlabel('X (m)')
# ax3.set_ylabel('Y (m)')
# ax3.set_title('XY Plane Projection')
# ax3.legend()
# ax3.grid(True)
#
# # 4. XZ平面投影
# ax4 = fig.add_subplot(2, 2, 4)
# ax4.plot(missile_x, missile_z, 'r-', label='Missile')
# ax4.plot(line_x, line_z, 'g--', label='Line of Sight')
#
# for i in range(3):
#     ax4.scatter(FY[i, 0], FY[i, 2], color=colors[i], marker=markers[i], s=100, label=f'FY{i + 1}')
#
# for i, p in enumerate(plan):
#     ax4.scatter(p.D[0], p.D[2], color=colors[p.uav], marker='*', s=150, label=f'FY{p.uav + 1} Release')
#     ax4.scatter(p.C0[0], p.C0[2], color=colors[p.uav], marker='X', s=150, label=f'FY{p.uav + 1} Detonation')
#
# ax4.scatter(T[0], T[2], color='black', marker='P', s=200, label='True Target')
# ax4.scatter(Of[0], Of[2], color='orange', marker='D', s=200, label='False Target')
#
# ax4.set_xlabel('X (m)')
# ax4.set_ylabel('Z (m)')
# ax4.set_title('XZ Plane Projection')
# ax4.legend()
# ax4.grid(True)
#
# plt.tight_layout()
# plt.show()
#
# # 打印总结信息
# print(f"\nVisualization Summary:")
# print(f"Total obscuration time: {total_cov:.2f} seconds")
# print(f"UAVs used: {[f'FY{i + 1}' for i in range(3) if uav_used[i]]}")

import numpy as np
from scipy.optimize import minimize_scalar
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置中文字体
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

# ============ 场景常量 ============
g = 9.81  # m/s^2
R = 10.0  # 有效遮蔽半径（云团中心 10 m）
v_sink = 3  # 云团中心下沉速度 m/s
valid_win = 20  # 起爆后有效 20 s
T = np.array([0, 200, 0])  # 真目标中心
Of = np.array([0, 0, 0])  # 假目标（原点）

# 导弹 M1
M0 = np.array([20000, 0, 2000])
uM = (Of - M0) / np.linalg.norm(Of - M0)  # 朝向假目标
vM = 300 * uM  # 速度 300 m/s
L = np.linalg.norm(Of - M0)
t_hit = L / 300  # 抵达假目标时间 ~ 67 s

# 三架 UAV 初始位置（等高度直线飞行，z 保持不变）
FY = np.array([
    [17800, 0, 1800],  # FY1
    [12000, 1400, 1400],  # FY2
    [6000, -3000, 700]  # FY3
])
v_min = 70
v_max = 140

# ============ 搜索网格（可调） ============
angles = np.deg2rad(np.arange(-180, 180, 22.5))  # 航向角（相对 +x 逆时针）
speeds = np.arange(70, 150, 10)  # 速度
t_grid = np.arange(2, t_hit - 2, 2)  # 候选起爆时刻（全局时间）
tau_set = np.array([2.4, 3.0, 3.6, 4.2])  # 候选引信延时
dt_eval = 0.02  # 评估时间步长

# ============ 预计算导弹/视线量 ============
ts = np.arange(0, t_hit - 1e-6, dt_eval)  # 避免 t_hit 处除零
N = len(ts)
Mx = M0[0] + vM[0] * ts
My = M0[1] + vM[1] * ts
Mz = M0[2] + vM[2] * ts
Ux = T[0] - Mx
Uy = T[1] - My
Uz = T[2] - Mz
UU = Ux ** 2 + Uy ** 2 + Uz ** 2


# ============ 计算单弹遮蔽时间的函数 ============
def calculate_single_shot_coverage(F0, uxF, uyF, vF, t_det, tau, z0):
    """计算单枚烟幕干扰弹的遮蔽时间"""
    # 起爆点
    x_det = F0[0] + vF * uxF * t_det
    y_det = F0[1] + vF * uyF * t_det
    z_det = z0 - 0.5 * g * tau ** 2

    # 云团中心轨迹
    valid = (ts >= t_det) & (ts <= t_det + valid_win)
    Cz = z_det - v_sink * (ts - t_det)

    # 该弹对"导弹->真目标"线段的最小距离 d_k(t)
    Wx = x_det - Mx
    Wy = y_det - My
    Wz = Cz - Mz

    WU = Wx * Ux + Wy * Uy + Wz * Uz
    lam = WU / UU
    lam = np.clip(lam, 0, 1)

    Px = Mx + lam * Ux
    Py = My + lam * Uy
    Pz = Mz + lam * Uz

    dx = x_det - Px
    dy = y_det - Py
    dz = Cz - Pz
    d_k = np.sqrt(dx ** 2 + dy ** 2 + dz ** 2)
    d_k[~valid] = np.inf

    # 计算遮蔽时间
    coverage = d_k <= R
    coverage_time = np.sum(coverage) * dt_eval

    return coverage_time, d_k


# ============ 贪心三弹（跨三架 UAV） ============
dmin_all = np.full(N, np.inf)  # 当前联合最小距离
uav_used = np.zeros(3, dtype=bool)  # 每架 UAV 仅用一次


# 定义计划结构
class Plan:
    def __init__(self):
        self.uav = 0
        self.theta = 0
        self.v = 0
        self.t_rel = 0
        self.tau = 0
        self.t_det = 0
        self.D = np.zeros(3)
        self.C0 = np.zeros(3)
        self.single_time = 0  # 单弹遮蔽时间
        self.d_k = None  # 单弹距离序列


plan = []
single_shot_times = []  # 存储每枚弹的单弹遮蔽时间

for shot in range(3):
    best_gain = -np.inf
    best_info = Plan()
    best_dmin_new = None

    for iu in range(3):
        if uav_used[iu]:
            continue

        F0 = FY[iu, :]
        z0 = F0[2]

        for ia in range(len(angles)):
            theta = angles[ia]
            uxF = np.cos(theta)
            uyF = np.sin(theta)

            for iv in range(len(speeds)):
                vF = speeds[iv]

                for id in range(len(t_grid)):
                    t_det = t_grid[id]

                    for it in range(len(tau_set)):
                        tau = tau_set[it]
                        t_rel = t_det - tau

                        if t_rel < 0:
                            continue

                        # 计算单弹遮蔽时间
                        single_time, d_k = calculate_single_shot_coverage(F0, uxF, uyF, vF, t_det, tau, z0)

                        # 与现有联合取最小
                        dmin_new = np.minimum(dmin_all, d_k)
                        gain = np.sum(dmin_new <= R) * dt_eval

                        if gain > best_gain:
                            best_gain = gain
                            best_dmin_new = dmin_new.copy()

                            best_info = Plan()
                            best_info.uav = iu
                            best_info.theta = theta
                            best_info.v = vF
                            best_info.t_rel = t_rel
                            best_info.tau = tau
                            best_info.t_det = t_det
                            best_info.D = np.array([
                                F0[0] + vF * uxF * t_rel,
                                F0[1] + vF * uyF * t_rel,
                                z0
                            ])
                            best_info.C0 = np.array([
                                F0[0] + vF * uxF * t_det,
                                F0[1] + vF * uyF * t_det,
                                z0 - 0.5 * g * tau ** 2
                            ])
                            best_info.single_time = single_time
                            best_info.d_k = d_k.copy()

    # 接受该次最优
    if best_gain == -np.inf:
        print(f'Warning: No feasible solution found for shot {shot + 1}.')
        break

    dmin_all = best_dmin_new
    uav_used[best_info.uav] = True
    plan.append(best_info)
    single_shot_times.append(best_info.single_time)

total_cov = np.sum(dmin_all <= R) * dt_eval

# ============ 输出结果 ============
print('========= 问题 4: 最优遮蔽策略 (FY1, FY2, FY3 → M1) =========')
for k, p in enumerate(plan):
    name = f'FY{p.uav + 1}'
    print(f'—— {name} ——')
    print(f'航向角 θ = {np.rad2deg(p.theta):.2f}° (相对 +x 轴逆时针)')
    print(f'飞行速度 v = {p.v:.2f} m/s')
    print(f'投放时刻 t_rel = {p.t_rel:.3f} s')
    print(f'引信延时 τ = {p.tau:.3f} s')
    print(f'起爆时刻 t_det = {p.t_det:.3f} s')
    print(f'投放点 D = ({p.D[0]:.3f}, {p.D[1]:.3f}, {p.D[2]:.3f}) m')
    print(f'起爆点 C0 = ({p.C0[0]:.3f}, {p.C0[1]:.3f}, {p.C0[2]:.3f}) m')
    print(f'单弹有效遮蔽时间 = {p.single_time:.3f} s\n')

print(f'三弹联合遮蔽总时长 = {total_cov:.6f} s')
print(f'单弹遮蔽时间序列: {[f"{t:.3f}s" for t in single_shot_times]}')
print(f'单弹平均遮蔽时间 = {np.mean(single_shot_times):.3f} s')

if total_cov > 60 + 1e-6:
    print('警告：理论最大值为 60 s (每弹 20 s)，当前值超过理论值，请检查网格/步长设置。')

# ============ 可视化 ============
fig = plt.figure(figsize=(15, 10))

# 1. 3D轨迹图
ax1 = fig.add_subplot(2, 2, 1, projection='3d')
colors = ['red', 'blue', 'green']
markers = ['o', 's', '^']

# 绘制导弹轨迹
missile_t = np.linspace(0, t_hit, 100)
missile_x = M0[0] + vM[0] * missile_t
missile_y = M0[1] + vM[1] * missile_t
missile_z = M0[2] + vM[2] * missile_t
ax1.plot(missile_x, missile_y, missile_z, 'r-', label='导弹轨迹')

# 绘制视线
line_x = np.linspace(M0[0], T[0], 100)
line_y = np.linspace(M0[1], T[1], 100)
line_z = np.linspace(M0[2], T[2], 100)
ax1.plot(line_x, line_y, line_z, 'g--', label='视线')

# 绘制UAV初始位置和轨迹
for i in range(3):
    ax1.scatter(FY[i, 0], FY[i, 1], FY[i, 2], color=colors[i], marker=markers[i], s=100, label=f'FY{i + 1} 起始点')

    # 绘制UAV飞行方向（简化的直线）
    if i < len(plan):
        p = plan[i]
        uav_dir_x = np.array([FY[i, 0], FY[i, 0] + 2000 * np.cos(p.theta)])
        uav_dir_y = np.array([FY[i, 1], FY[i, 1] + 2000 * np.sin(p.theta)])
        uav_dir_z = np.array([FY[i, 2], FY[i, 2]])
        ax1.plot(uav_dir_x, uav_dir_y, uav_dir_z, color=colors[i], linestyle=':', alpha=0.7)

# 绘制投放点和起爆点
for i, p in enumerate(plan):
    ax1.scatter(p.D[0], p.D[1], p.D[2], color=colors[p.uav], marker='*', s=150, label=f'FY{p.uav + 1} 投放点')
    ax1.scatter(p.C0[0], p.C0[1], p.C0[2], color=colors[p.uav], marker='X', s=150, label=f'FY{p.uav + 1} 起爆点')

# 标记目标点
ax1.scatter(T[0], T[1], T[2], color='black', marker='P', s=200, label='真目标')
ax1.scatter(Of[0], Of[1], Of[2], color='orange', marker='D', s=200, label='假目标')

ax1.set_xlabel('X (m)')
ax1.set_ylabel('Y (m)')
ax1.set_zlabel('Z (m)')
ax1.set_title('3D 轨迹概览')
ax1.legend(bbox_to_anchor=(1.05, 1), loc='upper left')

# 2. 遮蔽效果时间序列
ax2 = fig.add_subplot(2, 2, 2)
ax2.plot(ts, dmin_all, 'b-', label='到视线的最小距离')
ax2.axhline(y=R, color='r', linestyle='--', label='有效半径 (10m)')
ax2.fill_between(ts, 0, R, where=(dmin_all <= R), alpha=0.3, color='green', label='遮蔽区域')

# 标记起爆时刻和显示单弹时间
for i, p in enumerate(plan):
    ax2.axvline(x=p.t_det, color=colors[p.uav], linestyle='--', alpha=0.7,
                label=f'FY{p.uav + 1} 起爆 (单弹:{p.single_time:.1f}s)')

ax2.set_xlabel('时间 (s)')
ax2.set_ylabel('距离 (m)')
ax2.set_title('遮蔽效果时间序列')
ax2.legend()
ax2.grid(True)

# 3. XY平面投影
ax3 = fig.add_subplot(2, 2, 3)
ax3.plot(missile_x, missile_y, 'r-', label='导弹')
ax3.plot(line_x, line_y, 'g--', label='视线')

for i in range(3):
    ax3.scatter(FY[i, 0], FY[i, 1], color=colors[i], marker=markers[i], s=100, label=f'FY{i + 1}')

for i, p in enumerate(plan):
    ax3.scatter(p.D[0], p.D[1], color=colors[p.uav], marker='*', s=150, label=f'FY{p.uav + 1} 投放点')
    ax3.scatter(p.C0[0], p.C0[1], color=colors[p.uav], marker='X', s=150, label=f'FY{p.uav + 1} 起爆点')

ax3.scatter(T[0], T[1], color='black', marker='P', s=200, label='真目标')
ax3.scatter(Of[0], Of[1], color='orange', marker='D', s=200, label='假目标')

ax3.set_xlabel('X (m)')
ax3.set_ylabel('Y (m)')
ax3.set_title('XY 平面投影')
ax3.legend()
ax3.grid(True)

# 4. XZ平面投影
ax4 = fig.add_subplot(2, 2, 4)
ax4.plot(missile_x, missile_z, 'r-', label='导弹')
ax4.plot(line_x, line_z, 'g--', label='视线')

for i in range(3):
    ax4.scatter(FY[i, 0], FY[i, 2], color=colors[i], marker=markers[i], s=100, label=f'FY{i + 1}')

for i, p in enumerate(plan):
    ax4.scatter(p.D[0], p.D[2], color=colors[p.uav], marker='*', s=150, label=f'FY{p.uav + 1} 投放点')
    ax4.scatter(p.C0[0], p.C0[2], color=colors[p.uav], marker='X', s=150, label=f'FY{p.uav + 1} 起爆点')

ax4.scatter(T[0], T[2], color='black', marker='P', s=200, label='真目标')
ax4.scatter(Of[0], Of[2], color='orange', marker='D', s=200, label='假目标')

ax4.set_xlabel('X (m)')
ax4.set_ylabel('Z (m)')
ax4.set_title('XZ 平面投影')
ax4.legend()
ax4.grid(True)

plt.tight_layout()
plt.show()

# 打印总结信息
print(f"\n可视化总结:")
print(f"总遮蔽时间: {total_cov:.2f} 秒")
print(f"使用的无人机: {[f'FY{i + 1}' for i in range(3) if uav_used[i]]}")
print(f"单弹遮蔽时间: {[f'{t:.2f}s' for t in single_shot_times]}")